/*
 * Copyright 2009 Cedric Priscal
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android_serialport_api;

import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;

//20201014 添加注释,移动辅助函数到工具类中

public class ComPort {
    private static String TAG = "ComPort";

    protected SerialPort mSerialPort;
    protected OutputStream mOutputStream;
    public InputStream mInputStream;
    private ReadThread mReadThread;

    public String mComname;
    int boardRate = 115200;
    private static ComPort comPort;

    public interface DataHandler {
        void onDataReceived(String comName, byte[] buffer, int size);
    }

    DataHandler dataHandler;

    private class ReadThread extends Thread {
        byte[] buffer = new byte[1024];

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                try {
                    if (mInputStream == null) return;
                    int size = mInputStream.read(buffer);
                    if (size > 0) {
                        onDataReceived(buffer, size);
                    }
                    Thread.sleep(100);
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                    return;
                }
            }
            Log.i("Comport", "Com read thread exit.");
        }//end of run
    }//end of class ReadThread

    public ComPort() {
    }

    public static ComPort getInstance() {
        if (comPort == null) {
            comPort = new ComPort();
        }
        return comPort;
    }

    //防止切换activity后无法处理数据
    public void setHandler(DataHandler handler) {
        dataHandler = handler;
    }

    boolean isOpen = false;

    //串口使用3步骤 1.open 2.sendData 3.close 收到的数据会调用DataHandler
    public boolean open(String com_name, int boardRate, DataHandler handler) {
        dataHandler = handler;
        mComname = com_name;
        this.boardRate = boardRate;

        //防止重复打开
        if (isOpen) {
            Log.e("Comport", "this comport has opened.Don't open again or you should close before open.");
            return false;
        }

        try {
            if (mSerialPort == null) {
                mSerialPort = new SerialPort();
                boolean bOpen = mSerialPort.openPort(new File(mComname), boardRate, 0);
                if (bOpen == false) return bOpen;
            }

            if (mOutputStream == null) mOutputStream = mSerialPort.getOutputStream();

            if (mInputStream == null) mInputStream = mSerialPort.getInputStream();

            /* Create a receiving thread */
            if (mReadThread == null) {
                mReadThread = new ReadThread();
                mReadThread.start();
            }
            isOpen = true;
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InvalidParameterException e) {
            e.printStackTrace();
        }

        return true;
    }

    public void close() {
        isOpen = false;

        try {
            if (mOutputStream != null) {
                mOutputStream.close();
                mOutputStream = null;
            }

            if (mInputStream != null) {
                mInputStream.close();
                mInputStream = null;
            }
        } catch (IOException es) {

        }

        if (mReadThread != null) {
            mReadThread.interrupt();
            mReadThread = null;
        }

        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
    }

    public void sendData(String buffer) {
        Log.d("发送命令", buffer);
        synchronized (this) {
            try {
//				System.out.println("send to com" + bytes2HexString( buffer, size));
                byte[] buff = hex2byte(buffer);
                if (mOutputStream != null) {
                    mOutputStream.write(buff, 0, buff.length);
                    mOutputStream.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static byte[] hex2byte(String hex) {
        String digital = "0123456789ABCDEF";
        String hex1 = hex.replace(" ", "");
        char[] hex2char = hex1.toCharArray();
        byte[] bytes = new byte[hex1.length() / 2];
        byte temp;
        for (int p = 0; p < bytes.length; p++) {
            temp = (byte) (digital.indexOf(hex2char[2 * p]) * 16);
            temp += digital.indexOf(hex2char[2 * p + 1]);
            bytes[p] = (byte) (temp & 0xff);
        }
        return bytes;
    }

    private void onDataReceived(byte[] buffer, int size) {
        if (dataHandler != null) dataHandler.onDataReceived(mComname, buffer, size);
    }
}
